package com.niuwa.p2p.service.impl.productTemplate;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.niuwa.p2p.core.mvc.entity.PageBean;
import com.niuwa.p2p.core.utils.DictConstant;
import com.niuwa.p2p.dao.productTemplate.AreaPropCfgDao;
import com.niuwa.p2p.dao.productTemplate.ProdPropertyDao;
import com.niuwa.p2p.dao.productTemplate.ProductTemplateDao;
import com.niuwa.p2p.dao.productTemplate.TempPropConfigDao;
import com.niuwa.p2p.dao.productTemplate.TemplateAuditDao;
import com.niuwa.p2p.dao.productTemplate.TemplateProtocolDao;
import com.niuwa.p2p.dao.protocol.ProtocolDao;
import com.niuwa.p2p.entity.PageQuery;
import com.niuwa.p2p.entity.productTemplate.AreaPropCfg;
import com.niuwa.p2p.entity.productTemplate.ProductProperty;
import com.niuwa.p2p.entity.productTemplate.ProductProtocol;
import com.niuwa.p2p.entity.productTemplate.ProductTemplate;
import com.niuwa.p2p.entity.productTemplate.TempPropConfig;
import com.niuwa.p2p.entity.productTemplate.TemplateAudit;
import com.niuwa.p2p.entity.productTemplate.TemplateProtocol;
import com.niuwa.p2p.exception.BusinessException;
import com.niuwa.p2p.service.productTemplate.IInvestProdTemplateService;
import com.niuwa.p2p.service.sequence.ISequenceService;
import com.niuwa.p2p.vo.productTemplate.InvestProdTemplateVo;
import com.niuwa.p2p.vo.productTemplate.InvestProdTmptForm;
import com.niuwa.p2p.vo.productTemplate.InvestProdTmptVo;

@Service
public class InvestProdTemplateServiceImpl implements
		IInvestProdTemplateService {

	@Autowired
	private ProductTemplateDao productTemplateDao;

	@Autowired
	private TemplateAuditDao templateAuditDao;

	@Autowired
	private ProdPropertyDao prodPropertyDao; 
	
	@Autowired
	private TempPropConfigDao tempPropConfigDao;
	
	@Autowired
	private AreaPropCfgDao areaPropCfgDao;
	
	@Autowired
	private ISequenceService sequenceService;
	
	@Autowired
	private TemplateProtocolDao templateProtocolDao;
	
	@Autowired
	private ProtocolDao protocolDao;
	
	/**
	 * 分页查询产品模板集合 根据paramMap，选取需要的产品模板集合
	 * 
	 * @param paramMap
	 *            过滤得条件Map
	 * @return PageBean<CustomerVo> 分页信息与分页数据集合（产品模板集合）
	 */
	@Override
	public PageBean<InvestProdTemplateVo> search(Map<String, Object> paramMap) {

		assert paramMap.get(PageQuery.PAGEQUERY) != null;
		
		//删除标识：未删除
		paramMap.put("delFlag", DictConstant.FlagStatus.N);

		int totalCount = productTemplateDao.count(paramMap);

		PageBean<InvestProdTemplateVo> page = new PageBean<InvestProdTemplateVo>(
				totalCount);

		// 设置当前页
		page.setPage(((PageQuery) paramMap.get(PageQuery.PAGEQUERY)).getPage());

		page.setRows(productTemplateDao
				.selectInvestProdTemplateBySelective(paramMap));

		return page;
	}

	/**
	 * 删除产品模板
	 * 
	 * @param tempId
	 *            产品模板ID
	 * @return 更新条数
	 * @throws 删除失败
	 *             (更新DB失败)
	 */
	@Override
	public int deleteProductTmplt(long tempId) throws Exception {
		// 取得产品模板
		ProductTemplate productTemplate = productTemplateDao
				.selectByTempId(tempId);
		// 不存在,抛出错误
		if (productTemplate == null) {
			throw new BusinessException(
					"investProdTemplateService.prodTemplateIsNotExist");
		}
		
		int result = 0;
		//待审核从数据库删除,未通过逻辑删除
		if("WAIT".equals(productTemplate.getTempStatus())){
			// 删除产品模板
			result = productTemplateDao.deleteByTempId(tempId);
		}else if("NO_PASS".equalsIgnoreCase(productTemplate.getTempStatus())){
			// 删除产品模板
			result = productTemplateDao.updateByTempId(tempId);
		}
		
		
		if (result != 1) {
			throw new BusinessException(
					"investProdTemplateService.failTODelete");
		}
		return result;
	}

	/**
	 * 通过审批
	 * 
	 * @param tempId
	 *            产品模板ID
	 * @return 更新条数
	 * @throws 更新失败
	 *             (更新产品模板状态失败, 添加审批记录失败)
	 */
	@Override
	public int updateProductTmpltToPass(long tempId, long operatorId)
			throws Exception {
		// 取得产品模板
		ProductTemplate productTemplate = productTemplateDao
				.selectByTempId(tempId);
		// 不存在,抛出错误
		if (productTemplate == null) {
			throw new BusinessException(
					"investProdTemplateService.prodTemplateIsNotExist");
		}
		// 添加审批记录
		TemplateAudit templateAudit = new TemplateAudit();
		templateAudit.setTempId(tempId);
		templateAudit.setOperateType(DictConstant.OperateType.PASS.getCode());
		templateAudit.setOperator(operatorId);
		int result = templateAuditDao.insertTemplateAudit(templateAudit);
		if (result != 1) {
			throw new BusinessException(
					"investTemplateAuditService.failTOInsert");
		}
		// 更新产品模板状
		productTemplate.setTempStatus(DictConstant.TempStatus.PASS.getCode());
		result = productTemplateDao
				.updateByProductTemplateSelective(productTemplate);
		if (result != 1) {
			throw new BusinessException("investProdTemplateService.failTOPass");
		}
		return result;
	}

	/**
	 * 拒绝审批
	 * 
	 * @param tempId
	 *            产品模板ID
	 * @param rejectReason
	 *            拒绝理由
	 * @return 更新条数
	 * @throws 更新失败
	 *             (更新产品模板状态失败, 添加审批记录失败)
	 */
	@Override
	public int updateProductTmpltToReject(long tempId, String rejectReason,
			long operatorId) throws Exception {
		// 取得产品模板
		ProductTemplate productTemplate = productTemplateDao
				.selectByTempId(tempId);
		// 不存在,抛出错误
		if (productTemplate == null) {
			throw new BusinessException(
					"investProdTemplateService.prodTemplateIsNotExist");
		}
		// 添加审批记录
		TemplateAudit templateAudit = new TemplateAudit();
		templateAudit.setTempId(tempId);
		templateAudit.setOperateType(DictConstant.OperateType.REJECT.getCode());
		templateAudit.setOperator(operatorId);
		templateAudit.setRemark(rejectReason);
		int result = templateAuditDao.insertTemplateAudit(templateAudit);
		if (result != 1) {
			throw new BusinessException(
					"investTemplateAuditService.failTOInsert");
		}
		// 更新产品模板状
		productTemplate
				.setTempStatus(DictConstant.TempStatus.NO_PASS.getCode());
		result = productTemplateDao
				.updateByProductTemplateSelective(productTemplate);
		if (result != 1) {
			throw new BusinessException("investProdTemplateService.failTORject");
		}
		return result;
	}

	@Override
	public void addInestProductTmplt(long userId, InvestProdTmptForm form)
			throws Exception {

		// 保存产品模板基本信息（p2p_product_template）
		ProductTemplate pt = new ProductTemplate();
		pt.setTempName(form.getTempName());
		pt.setTempCode(sequenceService.getCompleteSequenceBySeqKey("MBTZ")); // 从数据库中获取
		pt.setMainVersion(Integer.parseInt(form.getMainVersion()));
		pt.setMinorVersion(Integer.parseInt(form.getMinorVersion()));
		pt.setTempStatus(DictConstant.TempStatus.WAIT.getCode()); // 待审核
		pt.setTempType(DictConstant.ProdTemplateType.INVEST_PT.getCode()); // 投资产品模板
		pt.setProdCount(0); // 初始关联未到期产品的个数为0
		pt.setOperator(userId);
		pt.setActiveTime(form.getActiveTime());
		pt.setCreateTime(new Date());
		pt.setDelFlag("N"); // 初始值：不是删除标识
		productTemplateDao.addProductTemplate(pt);
		
		long tempId = pt.getTempId();

		// 保存产品属性（1、基本信息，2、区间信息）（p2p_temp_prop_config和p2p_area_prop_cfg表）
		this.addTempPropConfig(tempId, form); // 新增产品属性列表
		
		/*if("Y".equals(form.getIsCheckedOverdueFees())) { // 如果选中逾期服务费区间
			this.addAreaPropCfg(tempId, form); // 新增产品区间信息
		}*/
		
		// 保存产品模与产品协议对应信息（p2p_template_protocol）
		if(null != form.getProtId() && form.getProtId().length > 0)
			this.addTemplateProtocol(tempId, form);

		// 保存模板审核信息（p2p_template_audit）
		TemplateAudit ta = new TemplateAudit();
		ta.setTempId(tempId);
		ta.setOperateType(DictConstant.TempStatus.WAIT.getCode());
		ta.setRemark("投资产品模板提交审核");
		ta.setOperator(userId);
		templateAuditDao.insertTemplateAudit(ta);
	}

	/**
	 * 新增选中的协议信息列表
	 * 
	 * @param tempId
	 * @param form
	 */
	private void addTemplateProtocol(long tempId, InvestProdTmptForm form) {
		String[] pids = form.getProtId();
		List<TemplateProtocol> tpList = new ArrayList<TemplateProtocol>();
		for (int index = 0; index < pids.length; index++) {
			TemplateProtocol tp = new TemplateProtocol();
			tp.setTempId(tempId);
			if(null != pids[index] && !"".equals(pids[index]))
				tp.setProtId(Long.valueOf(pids[index]));
			tpList.add(tp);
		}
		templateProtocolDao.addTemplateProtocol(tpList);
	}

	/**
	 * 新增区间值
	 * 
	 * @param tempId
	 * @param form
	 */
	/*private void addAreaPropCfg(long tempId, InvestProdTmptForm form) {
		
		// 起始条件集合
		String[] startConds = form.getStartCond();
		
		// 截止条件集合
		String[] endConds = form.getEndCond();
		
		// 属性值集合
		String[] values = form.getAreaValue();
		
		List<AreaPropCfg> list = new ArrayList<AreaPropCfg>();
		
		for (int index = 0; index < startConds.length; index++) {
			AreaPropCfg apc = new AreaPropCfg();
			apc.setPropCfgId(0); //TODO 需要重新设计表
			apc.setTempId(tempId);
			// 属性值
			if(null != values[index] && !"".equals(values[index])) {
				apc.setAreaValue(new BigDecimal(values[index]));
			}
			// 起始条件
			if(null != startConds[index] && !"".equals(startConds[index])) {
				apc.setStartCond(Integer.parseInt(startConds[index]));
			}
			// 截止条件
			if(null != endConds[index] && !"".equals(endConds[index])){
				apc.setEndCond(Integer.parseInt(endConds[index]));
			}
			apc.setAreaUnitType("OVERDUE_UNIT_TYPE"); // 目前只有逾期服务费（%）类型
			apc.setAreaUnitValue(form.getAreaUnitValue());
			list.add(apc);
		}
		
		areaPropCfgDao.addAreaPropCfg(list);
	}*/

	/**
	 * 新增产品模板
	 * 
	 * @param tempId
	 *            产品模板ID
	 * @param form
	 */
	private void addTempPropConfig(long tempId, InvestProdTmptForm form) {

		// 产品属性表
		List<ProductProperty> ppList = 
				prodPropertyDao.searchAll(DictConstant.ProdTemplateType.INVEST_PT.getCode());

		List<TempPropConfig> tpcList = new ArrayList<TempPropConfig>();

		for (ProductProperty pp : ppList) {
			String propCode = pp.getPropCode();
			String propValue = this.getPropValue("", propCode, form);

			TempPropConfig tpc = new TempPropConfig();
			tpc.setTempId(tempId);
			tpc.setPropName(pp.getPropName());
			tpc.setPropCode(propCode);
			tpc.setPropValue(propValue);
			tpc.setSetType(this.getPropValue("SETYPE_", propCode, form));

			if ("OVERDUE_FEES".equals(propCode)) { // 逾期服务费（%） 需要判断是否选中区间
				
				tpc.setIsAreaProp("Y"); // 是区间属性
				
				// 判断是否选中区间值
/*				if ("Y".equals(form.getIsCheckedOverdueFees())) 
					tpc.setSelectedArea("Y");
				else 
					tpc.setSelectedArea("N");
*/				
			} else {
				tpc.setIsAreaProp("N"); // 不是区间属性
			}
			tpcList.add(tpc);
		}
		tempPropConfigDao.addTempPropConfig(tpcList);
	}

	/**
	 * 循环读取页面上的值
	 * 
	 * @param propCode
	 * @param form
	 * @return String
	 */
	private String getPropValue(String prefix, String propCode,
			InvestProdTmptForm form) {
		Object result = null;
		Object[] args = new Object[] {};
		String methodName = "get" + prefix + propCode;
		try {
			Method[] methods = form.getClass().getMethods();
			for (Method method : methods) {
				if (methodName.equals(method.getName())) {
					result = method.invoke(form, args);
				}
			}
		} catch (IllegalAccessException | IllegalArgumentException
				| InvocationTargetException e) {
			e.printStackTrace();
		}
		return null == result ? "" : result.toString();
	}
	
	@Override
	public InvestProdTmptVo getProdTmptById(long tempId){
		
		InvestProdTmptVo iptv = new InvestProdTmptVo();
		
		InvestProdTmptForm iptf = new InvestProdTmptForm();
		
		// 获取产品模板基本信息
		ProductTemplate pt = productTemplateDao.selectByTempId(tempId);
		iptf.setTempCode(pt.getTempCode());
		iptf.setTempName(pt.getTempName());
		iptf.setMainVersion(String.valueOf(pt.getMainVersion()));
		iptf.setMinorVersion(String.valueOf(pt.getMinorVersion() + 1));
		iptf.setActiveTime(pt.getActiveTime());
		iptf.setTempId(pt.getTempId());
		
		// 获取产品属性列表信息
		List<TempPropConfig> tpcList = tempPropConfigDao.getTpcListByTempId(tempId);
		for(TempPropConfig tpc : tpcList) {
			
			// 设置属性值和设置类型 
			this.setInvestProdTmptForm(tpc, iptf);
			
			// 设置 是否是区间属性
			/*if(null != tpc.getPropCode() && "OVERDUE_FEES".equals(tpc.getPropCode())) {
				if(null != tpc.getSelectedArea() && "Y".equals(tpc.getSelectedArea())){
					iptf.setIsCheckedOverdueFees("Y");
				} else {
					iptf.setIsCheckedOverdueFees("N");
				}
			}*/
		}
		
		
		// 获取区间信息
		/*List<AreaPropCfg> apcList = areaPropCfgDao.getApcListByTempId(tempId);
		iptv.setApcList(apcList);
		
		if(null != apcList && apcList.size() > 0){
			iptf.setAreaUnitValue(apcList.get(0).getAreaUnitValue());
		}*/
		
		iptv.setTmptForm(iptf);
		
		// 获取协议信息
		List<ProductProtocol> ppList = protocolDao.getPpListByTempId(tempId);
		iptv.setPpList(ppList);
		
		return iptv;
	}

	private void setInvestProdTmptForm(TempPropConfig tpc,
			InvestProdTmptForm form) {
		
		String propCode = tpc.getPropCode();
		String propValue = tpc.getPropValue();
		String setType = tpc.getSetType();
		
		Class<InvestProdTmptForm> classz = InvestProdTmptForm.class;
		Method[] methods = classz.getDeclaredMethods();
		try {
			for(Method method : methods) {
				String name = method.getName();
				method.setAccessible(true);
				if(("set" + propCode).equals(name)) { // set普通属性
					method.invoke(form, propValue);
				}
				if(("setSETYPE_" + propCode).equals(name)) {
					method.invoke(form, setType);
				}
			}
		} catch (IllegalAccessException | IllegalArgumentException
				| InvocationTargetException e) {
			e.printStackTrace();
		}
	}

	@Override
	public List<ProductTemplate> findInvestProdTempByCondition(String type) {
		List<ProductTemplate> templates=null;
		try {
			Map<String, Object> paramMap =new HashMap<String, Object>();
			paramMap.put("delFlag", DictConstant.FlagStatus.N);//显示
			paramMap.put("tempType", type);//模板类型
			paramMap.put("tempStatus", DictConstant.TempStatus.PASS.getCode());//模板状态
			templates=productTemplateDao.findInvestProdTempByCondition(paramMap);
		} catch (Exception e) {
			e.printStackTrace();
			//TODO LOG
		}
		return templates;
	}

	@Override
	public List<InvestProdTemplateVo> findProdVersionByCondition(String tempName) {
		List<InvestProdTemplateVo> templates=null;
		try {
			Map<String, Object> paramMap =new HashMap<String, Object>();
			paramMap.put("delFlag", DictConstant.FlagStatus.N);//显示
			paramMap.put("tempName", tempName);//模板名称
			paramMap.put("tempStatus", DictConstant.TempStatus.PASS.getCode());//模板状态
			templates=productTemplateDao.findProdVersionByCondition(paramMap);
		} catch (Exception e) {
			e.printStackTrace();
			//TODO LOG
		}
		return templates;
	}

	
	@Override
	public Object findInvestProdTemplateByCondition(long tempId) {
		// 获取产品属性列表信息
		List<TempPropConfig> tpcList = tempPropConfigDao.getTpcListByTempId(tempId);
		
		// 获取区间信息
		List<AreaPropCfg> apcList = areaPropCfgDao.getApcListByTempId(tempId);
		
		// 获取协议信息
		List<ProductProtocol> ppList = protocolDao.getPpListByTempId(tempId);
				
		//遍历产品属性信息（判断是否存在区间值，如果存在，封装成String）
		StringBuffer sb=new StringBuffer();//保存区间值
		for (TempPropConfig tpc : tpcList) {
			if (tpc.getIsAreaProp().equals(DictConstant.FlagStatus.Y) && tpc.getSelectedArea().equals(DictConstant.FlagStatus.Y)) {
				for (AreaPropCfg apc : apcList) {
					if (tpc.getId()==apc.getPropCfgId()) {
						sb.append(apc.getStartCond()).append("~").append(apc.getEndCond()).append(" : ").append(apc.getAreaValue()).append(" | ");
					}
				}
				tpc.setPropValue(sb.toString());
			}
		}
		//定义集合保存模板属性（属性名称、属性值、属性状态[INDETERMINE：待定、HADSETTED：已设置、DEFAULT：缺省值、INVALID：无效项]）
		List<Object> fieldProperties=new LinkedList<Object>();
		fieldProperties.add(tpcList);
		fieldProperties.add(ppList);
		return fieldProperties;
	}

	@Override
	public int findProductTmptByName(ProductTemplate productTemplate) {
		return productTemplateDao.findProductTmptByName(productTemplate);
	}

}
